欢迎来到我的博客小站。  交流请加我微信好友: studyjava。  也欢迎关注公众号:Java学习之道 Fork me on GitHub

裸系统封装

封装过程:

1、建立一个web工程

  新建一个index.jsp;

 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP 'index.jsp' starting page</title>
13     <meta http-equiv="pragma" content="no-cache">
14     <meta http-equiv="cache-control" content="no-cache">
15     <meta http-equiv="expires" content="0">    
16     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17     <meta http-equiv="description" content="This is my page">
18     <!--
19     <link rel="stylesheet" type="text/css" href="styles.css">
20     -->
21   </head>
22   
23   <body>
24     This is my mmzs JSP page. <br>
25   </body>
26 </html>
index.jsp

  部署工程,测试是否可以部署成功。若成功访问请进入下一步:

2、接下来写一个登陆:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    <span style="font-size: 22px;font-weight: bolder;color: red">用户登陆</span>
    <hr color="green" size="2" width="100%" />
    <form id="loginForm" action="/BigData6-1/userAction" method="post">
        <input type="hidden" name="method" value="login">
        <input name="userName" ><br><br>
        <input name="passWord" type="password"  ><br><br>
        <input type="submit" value="登录">
    </form>
  </body>
</html>
login.jsp
工程结构: 

建立一个action基础类:

 1 package com.mmzs.bigdata.action;
 2 
 3 import java.io.IOException;
 4 import java.lang.reflect.InvocationTargetException;
 5 import java.lang.reflect.Method;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 public class BaseAction extends HttpServlet{
13 
14     @Override
15     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
16             throws ServletException, IOException {
17         this.doPost(req, resp);
18     }
19 
20     @Override
21     protected void doPost(HttpServletRequest request, HttpServletResponse response)
22             throws ServletException, IOException {
23         //获取当前客户端需要调用的逻辑控制方法
24         String methodName = request.getParameter("method");
25         if (null == methodName || methodName.trim().isEmpty()) return;
26         //获取当前客户端正在调用的Servlet类
27         Class actionClass = this.getClass();
28         try {
29             //从当前正在调用的Servlet类中查找需要调用的方法
30             Method method = actionClass.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
31             
32             //打破方法的封装权限
33             method.setAccessible(true);
34             
35             //调用控制器方法
36             method.invoke(this, request, response);
37         } catch (NoSuchMethodException e) {
38             e.printStackTrace();
39         } catch (SecurityException e) {
40             e.printStackTrace();
41         } catch (IllegalAccessException e) {
42             e.printStackTrace();
43         } catch (IllegalArgumentException e) {
44             e.printStackTrace();
45         } catch (InvocationTargetException e) {
46             e.printStackTrace();
47         }
48         
49     }
50 
51 }
BaseAction
这里要注意一下,doGet方法中调用doPost需要使用this.doPost(req, resp); 
然后启动tomcat访问http://localhost:8080/BigData6-1/userAction?method=login
 3、建立我们需要的数据库:
CREATE TABLE t_user(
userId INT(11) PRIMARY KEY auto_increment,
userName VARCHAR(30) not NULL,
`passWord` VARCHAR(30) not NULL,
realName VARCHAR(30) default null,
weight DOUBLE(6,2) default null,
height INT(3) default null,
birthday DATE default null
)ENGINE=INNODB CHARSET=utf8; 

SELECT * FROM t_user;

INSERT INTO t_user VALUES
(1,'ligang','123456','李刚',65.55,176,'1997-6-6'),
创建数据库的sql语句

在工程中导入jar包:mysql-connector-java-3.0.17-ga-bin.jar 

在工程中建立与数据库对应的po类:

package com.mmzs.bigdata.po;

import java.io.Serializable;
import java.sql.Date;

public class User implements Serializable {
    //支持序列化才能在磁盘之间转化为二进制进行传输
    private Integer userId;
    private String userName;
    private String passWord;
    private String realName;
    private Double weight;
    private Integer height;
    private Date birthday;
    
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public String getRealName() {
        return realName;
    }
    public void setRealName(String realName) {
        this.realName = realName;
    }
    public Double getWeight() {
        return weight;
    }
    public void setWeight(Double weight) {
        this.weight = weight;
    }
    public Integer getHeight() {
        return height;
    }
    public void setHeight(Integer height) {
        this.height = height;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return "User [userId=" + userId + ", userName=" + userName
                + ", passWord=" + passWord + ", realName=" + realName
                + ", weight=" + weight + ", height=" + height + ", birthday="
                + birthday + "]";
    }
    
    
}
User
4、建立dao层
  1 package com.mmzs.bigdata.dao;
  2 
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.lang.reflect.Method;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.PreparedStatement;
  8 import java.sql.ResultSet;
  9 import java.sql.ResultSetMetaData;
 10 import java.sql.SQLException;
 11 import java.util.ArrayList;
 12 import java.util.Date;
 13 import java.util.List;
 14 import java.util.Map;
 15 
 16 import com.mysql.jdbc.Field;
 17 
 18 public class BaseDao {
 19     
 20     private static String url;
 21     
 22     private static String driver;
 23     
 24     private static String userName;
 25     
 26     private static String passWord;
 27     
 28     static {
 29         url = "jdbc:mysql://127.0.0.1:3306/test?useUnique=true&characterEncoding=utf8";
 30         driver="com.mysql.jdbc.Driver";
 31         userName = "root";
 32         passWord = "123456";
 33         
 34         try {
 35             Class.forName(driver);
 36         } catch (ClassNotFoundException e) {
 37             e.printStackTrace();
 38         }
 39     }
 40     
 41     /**
 42      * 返回数据库链接
 43      * @return
 44      */
 45     public Connection getConnection() {
 46         Connection conn = null;
 47         try {
 48             conn = DriverManager.getConnection(url, userName, passWord);
 49         } catch (SQLException e) {
 50             e.printStackTrace();
 51         }
 52         
 53         return conn;
 54     }
 55     
 56     public <T> List<T> getEntityList(Class<T> entityClass, String sql, Object... params) {
 57         //获取数据库连接
 58         Connection conn = getConnection();
 59         if (null == conn) {
 60             return null;
 61         }
 62         //
 63         ResultSet res = null;
 64         //对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的
 65         PreparedStatement pstat = null;//import java.sql.PreparedStatement;
 66         List<T> list = new ArrayList<>();
 67         try {
 68             //预编译SQL语句
 69             pstat = conn.prepareStatement(sql);
 70             //为预编译好的SQL语句传递参数
 71             for (int i = 0; i < params.length; i++) {
 72                 pstat.setObject(i+1, params[i]);
 73             }
 74             //执行SQL语句并返回结果集
 75             res = pstat.executeQuery();
 76             //获取结果集元数据
 77             ResultSetMetaData rsmd = res.getMetaData();
 78             //获取结果集中列的数量(字段的数量)
 79             Integer columnNum = rsmd.getColumnCount();
 80             
 81             //简单类型包括数字类型、字符串类型和日期类型
 82             if (String.class.isAssignableFrom(entityClass) ||
 83                     Number.class.isAssignableFrom(entityClass) ||
 84                     Date.class.isAssignableFrom(entityClass)) {//简单类型
 85                 T t = null;
 86                 //遍历每一条记录
 87                 while (res.next()) {
 88                     //类型转换必须类型兼容;低类型向高类型自动转换,反之强制转换;
 89                     t = (T)res.getObject(1);//返回单例,索引只能去1
 90                     list.add(t);
 91                 }
 92             }else if(Map.class.isAssignableFrom(entityClass)) {//字典类型,Map是顶层接口
 93                 T t = null;
 94                 //获取的是类自身声明的所有方法
 95                 Method putMethod = entityClass.getDeclaredMethod("put", Object.class, Object.class);
 96                 while (res.next()) {
 97                     //调用反射调用Map实现累的无参数构造创建Map实例对象
 98                     t = entityClass.newInstance();
 99                     //循环每条记录中的各个字段
100                     for (int i = 0; i < columnNum; i++) {
101                         //获取列名(它对应于Map中的Key)
102                         String fieldName = rsmd.getColumnLabel(i+1);
103                         //获取列值(它对应于Map中的Value)
104                         Object fieldValue = res.getObject(fieldName);
105                         //调用put方法往Map中添加键值对
106                         putMethod.invoke(t, fieldName, fieldValue);
107                     }
108                     list.add(t);
109                 }
110             }else { //实体类型
111                 T t = null;
112                 while (res.next()) {
113                     //使用反射调用实体类的无参数构造创建实体对象
114                     t = entityClass.newInstance();
115                     for (int i = 0; i < columnNum; i++) {
116                         //获取结果集中的字段名(或别名)
117                         String fieldName = rsmd.getColumnLabel(i+1);
118                         //1.根据字段名获取字段值
119                         Object fieldValue = res.getObject(fieldName);
120                         //2.根据索引获取字段值
121                         //Object fieldValue = res.getObject(i+1);
122                         //getDeclaredField是可以获取一个类的所有字段. 
123                         //通过反射根据字段名查找实体类(User类)中的属性
124                         java.lang.reflect.Field field = entityClass.getDeclaredField(fieldName);
125                         //打开访问权限
126                         field.setAccessible(true);
127                         field.set(t, fieldValue);
128                     }
129                     list.add(t);
130                 }
131             }
132             return list;
133         } catch (SQLException e) {
134             e.printStackTrace();
135         } catch (NoSuchMethodException e) {
136             e.printStackTrace();
137         } catch (SecurityException e) {
138             e.printStackTrace();
139         } catch (InstantiationException e) {
140             e.printStackTrace();
141         } catch (IllegalAccessException e) {
142             e.printStackTrace();
143         } catch (IllegalArgumentException e) {
144             e.printStackTrace();
145         } catch (InvocationTargetException e) {
146             e.printStackTrace();
147         } catch (NoSuchFieldException e) {
148             e.printStackTrace();
149         }finally {
150             try {
151                 if (null != res) {
152                         res.close();
153                 }
154                 if (null != pstat) {
155                     pstat.close();
156                 }
157                 if (null != conn) {
158                     conn.close();
159                 }
160             } catch (SQLException e) {
161                 e.printStackTrace();
162             }
163         }
164         return null;
165     }
166     
167     
168     
169     
170     
171     
172 //    public static void main(String[] args) {
173 //        Connection conn = new BaseDao().getConnection();
174 //        System.err.println(conn);
175 //    }
176 }
BaseDao
1 package com.mmzs.bigdata.dao;
2 
3 import com.mmzs.bigdata.po.User;
4 
5 public interface UserDao {
6     public User selectUser(String userName, String passWord);
7 }
UserDao
 1 package com.mmzs.bigdata.dao;
 2 
 3 import java.util.List;
 4 
 5 import com.mmzs.bigdata.po.User;
 6 
 7 public class UserDaoImpl extends BaseDao implements UserDao {
 8 
 9     @Override
10     public User selectUser(String userName, String passWord) {
11         
12         String sql = "select * from t_user where userName=? and passWord=?";
13         List<User> userlist = this.getEntityList(User.class, sql, userName, passWord);
14         
15         return null!= userlist&&!userlist.isEmpty()?userlist.get(0):null;
16     }
17 
18     
19     
20     public static void main(String[] args) {
21         User user = new UserDaoImpl().selectUser("ligang", "123456");
22         System.err.println(user);
23     }
24 }
UserDaoImpl

 在UserDaoImpl中利用20-23行代码测试是否能从数据库中取到数据。

 5、建立service层

1 package com.mmzs.bigdata.service;
2 
3 import com.mmzs.bigdata.po.User;
4 
5 public interface UserService {
6     public User getUser(String userName, String passWord);
7 }
UserService
 1 package com.mmzs.bigdata.service;
 2 
 3 import com.mmzs.bigdata.po.User;
 4 
 5 public class UserServiceImpl implements UserService {
 6 
 7     @Override
 8     public User getUser(String userName, String passWord) {
 9         
10         return null;
11     }
12 
13 }
UserServiceImpl
 6、写自己的action类
 1 package com.mmzs.bigdata.action;
 2 
 3 import javax.servlet.http.HttpServletRequest;
 4 import javax.servlet.http.HttpServletResponse;
 5 
 6 /**
 7  * 用户模块控制器
 8  * @author Administrator
 9  *
10  */
11 public class UserAction extends BaseAction {
12     
13     /**
14      * 用户登录
15      * @param request
16      * @param response
17      */
18     public void login(HttpServletRequest request, HttpServletResponse response) {
19         String userName = request.getParameter("userName");
20         String passWord = request.getParameter("passWord");
21         System.out.println(userName+":"+passWord);
22     }
23 }
UserAction

 将userAction配置到web.xml文件中

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 3     <display-name>BigData6-1</display-name>
 4     
 5     <servlet>
 6         <servlet-name>userAction</servlet-name>
 7         <servlet-class>com.mmzs.bigdata.action.UserAction</servlet-class>
 8     </servlet>
 9     
10     <servlet-mapping>
11         <servlet-name>userAction</servlet-name>
12         <url-pattern>/userAction</url-pattern>
13     </servlet-mapping>
14     
15     
16     
17     
18     
19     
20     <welcome-file-list>
21         <welcome-file>index.jsp</welcome-file>
22     </welcome-file-list>
23 </web-app>
web.xml

==========这是华丽的分割线============

发现自己的BaseDao中getEntityList方法名字不优美;换成executeDQL,同时它的子类UserDaoImpl也作相应的修改;同时url后面传递的参数名子也做了优化。

然后继续封装其它的方法,继续完善BaseDao:

  1 package com.mmzs.bigdata.dao;
  2 
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.lang.reflect.Method;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.PreparedStatement;
  8 import java.sql.ResultSet;
  9 import java.sql.ResultSetMetaData;
 10 import java.sql.SQLException;
 11 import java.util.ArrayList;
 12 import java.util.Date;
 13 import java.util.List;
 14 import java.util.Map;
 15 
 16 import com.mysql.jdbc.Field;
 17 
 18 public class BaseDao {
 19     //URL指向要访问的数据库名mydata
 20     private static String url;
 21     //驱动程序名
 22     private static String driver;
 23     //MySQL配置时的用户名
 24     private static String userName;
 25     //MySQL配置时的密码
 26     private static String passWord;
 27     /**
 28      * 连接数据库的驱动
 29      */
 30     static {
 31         url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8";
 32         driver="com.mysql.jdbc.Driver";
 33         userName = "root";
 34         passWord = "123456";
 35         try {
 36             Class.forName(driver);//加载驱动类
 37         } catch (ClassNotFoundException e) {
 38             e.printStackTrace();
 39         }
 40     }
 41     
 42     /**
 43      * 返回数据库链接
 44      * @return
 45      */
 46     public Connection getConnection() {
 47         Connection conn = null;
 48         try {
 49             conn = DriverManager.getConnection(url, userName, passWord);
 50         } catch (SQLException e) {
 51             e.printStackTrace();
 52         }
 53         
 54         return conn;
 55     }
 56     
 57     /**
 58      * 执行通用插入操作
 59      * @param pkClass
 60      * @param sql
 61      * @param params
 62      * @return 主键列表(主键列表的长度代表插入函数的影响函数)
 63      */
 64     public <T> List<T> executeInsert(Class<T> pkClass, String sql, Object... params) {
 65         //获取数据库连接
 66         Connection conn = getConnection();
 67         if (null == conn) return null;
 68         
 69         T t = null;
 70         ResultSet pkRes = null;
 71         PreparedStatement pstat = null;
 72         List<T> pkList = new ArrayList<T>();
 73         try {
 74             //预编译SQL语句
 75             pstat = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
 76             //为预编译好的SQL语句传递参数
 77             for (int i = 0; i < params.length; i++) {
 78                 pstat.setObject(i+1, params[i]);
 79             }
 80             //执行增删改等操作返回影响的行数
 81             pstat.executeUpdate();
 82             //获取生成的主键结果集
 83             pkRes = pstat.getGeneratedKeys();
 84             //遍历主键结果集
 85             while (pkRes.next()) {
 86                 //主键结果集中的每一条记录只有一列(这一列代表主键值),所以只能取下标1
 87                 t = (T) pkRes.getObject(1);
 88                 pkList.add(t);
 89             }
 90             return pkList;
 91             
 92         } catch (SQLException e) {
 93             e.printStackTrace();
 94         }finally {
 95             try {
 96                 if (null != pkRes) {
 97                     pkRes.close();
 98                 }
 99                 if (null != pstat) {
100                     pstat.close();
101                 }
102                 if (null != conn) {
103                     conn.close();
104                 }
105             } catch (SQLException e) {
106                 e.printStackTrace();
107             }
108         }
109         
110         return null;
111     }
112     
113     /**
114      * 执行通用的增删改
115      * @param sql
116      * @param params
117      * @return 影响行数
118      */
119     public Integer executeDML(String sql, Object... params) {
120         //获取数据库连接
121         Connection conn = getConnection();
122         if (null == conn) return null;
123         
124         Integer count = null;
125         PreparedStatement pstat = null;
126         //为预编译好的SQL语句传递参数
127         try {
128             //预编译SQL语句
129             pstat = conn.prepareStatement(sql);
130             //为预编译好的SQL语句传递参数
131             for (int i = 0; i < params.length; i++) {
132                 pstat.setObject(i+1, params[i]);
133             }
134             //执行增删改等操作
135             count = pstat.executeUpdate();
136             return count;
137             
138         } catch (SQLException e) {
139             e.printStackTrace();
140         }finally {
141             try {
142                 if (null != pstat) {
143                     pstat.close();
144                 }
145                 if (null != conn) {
146                     conn.close();
147                 }
148             } catch (SQLException e) {
149                 e.printStackTrace();
150             }
151         }
152         return 0;
153     }
154     
155     /**
156      * 执行数据库查询操作
157      * @param entityClass
158      * @param sql
159      * @param params
160      * @return 结果集
161      */
162     public <T> List<T> executeDQL(Class<T> entityClass, String sql, Object... params) {
163         //获取数据库连接
164         Connection conn = getConnection();
165         if (null == conn) {
166             return null;
167         }
168         //
169         ResultSet res = null;
170         //对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的
171         PreparedStatement pstat = null;//import java.sql.PreparedStatement;
172         List<T> list = new ArrayList<>();
173         try {
174             //预编译SQL语句
175             pstat = conn.prepareStatement(sql);
176             //为预编译好的SQL语句传递参数
177             for (int i = 0; i < params.length; i++) {
178                 pstat.setObject(i+1, params[i]);
179             }
180             //执行SQL语句并返回结果集
181             res = pstat.executeQuery();
182             //获取结果集元数据
183             ResultSetMetaData rsmd = res.getMetaData();
184             //获取结果集中列的数量(字段的数量)
185             Integer columnNum = rsmd.getColumnCount();
186             
187             //简单类型包括数字类型、字符串类型和日期类型
188             if (String.class.isAssignableFrom(entityClass) ||
189                     Number.class.isAssignableFrom(entityClass) ||
190                     Date.class.isAssignableFrom(entityClass)) {//简单类型
191                 T t = null;
192                 //遍历每一条记录
193                 while (res.next()) {
194                     //类型转换必须类型兼容;低类型向高类型自动转换,反之强制转换;
195                     t = (T)res.getObject(1);//返回单例,索引只能去1
196                     list.add(t);
197                 }
198             }else if(Map.class.isAssignableFrom(entityClass)) {//字典类型,Map是顶层接口
199                 T t = null;
200                 //获取的是类自身声明的所有方法
201                 Method putMethod = entityClass.getDeclaredMethod("put", Object.class, Object.class);
202                 while (res.next()) {
203                     //调用反射调用Map实现累的无参数构造创建Map实例对象
204                     t = entityClass.newInstance();
205                     //循环每条记录中的各个字段
206                     for (int i = 0; i < columnNum; i++) {
207                         //获取列名(它对应于Map中的Key)
208                         String fieldName = rsmd.getColumnLabel(i+1);
209                         //获取列值(它对应于Map中的Value)
210                         Object fieldValue = res.getObject(fieldName);
211                         //调用put方法往Map中添加键值对
212                         putMethod.invoke(t, fieldName, fieldValue);
213                     }
214                     list.add(t);
215                 }
216             }else { //实体类型
217                 T t = null;
218                 while (res.next()) {
219                     //使用反射调用实体类的无参数构造创建实体对象
220                     t = entityClass.newInstance();
221                     for (int i = 0; i < columnNum; i++) {
222                         //获取结果集中的字段名(或别名)
223                         String fieldName = rsmd.getColumnLabel(i+1);
224                         //1.根据字段名获取字段值
225                         Object fieldValue = res.getObject(fieldName);
226                         //2.根据索引获取字段值
227                         //Object fieldValue = res.getObject(i+1);
228                         //getDeclaredField是可以获取一个类的所有字段. 
229                         //通过反射根据字段名查找实体类(User类)中的属性
230                         java.lang.reflect.Field field = entityClass.getDeclaredField(fieldName);
231                         //打开访问权限
232                         field.setAccessible(true);
233                         field.set(t, fieldValue);
234                     }
235                     list.add(t);
236                 }
237             }
238             return list;
239         } catch (SQLException e) {
240             e.printStackTrace();
241         } catch (NoSuchMethodException e) {
242             e.printStackTrace();
243         } catch (SecurityException e) {
244             e.printStackTrace();
245         } catch (InstantiationException e) {
246             e.printStackTrace();
247         } catch (IllegalAccessException e) {
248             e.printStackTrace();
249         } catch (IllegalArgumentException e) {
250             e.printStackTrace();
251         } catch (InvocationTargetException e) {
252             e.printStackTrace();
253         } catch (NoSuchFieldException e) {
254             e.printStackTrace();
255         }finally {
256             try {
257                 if (null != res) {
258                         res.close();
259                 }
260                 if (null != pstat) {
261                     pstat.close();
262                 }
263                 if (null != conn) {
264                     conn.close();
265                 }
266             } catch (SQLException e) {
267                 e.printStackTrace();
268             }
269         }
270         return null;
271     }
272     
273     
274     
275     
276     
277     
278 //    public static void main(String[] args) {
279 //        Connection conn = new BaseDao().getConnection();
280 //        System.err.println(conn);
281 //    }
282 }
BaseDao

在UserDaoImpl中测试:

 1 package com.mmzs.bigdata.dao;
 2 
 3 import java.sql.Date;
 4 import java.util.List;
 5 
 6 import com.mmzs.bigdata.po.User;
 7 
 8 public class UserDaoImpl extends BaseDao implements UserDao {
 9 
10     @Override
11     public User selectUser(String userName, String passWord) {
12         
13         String sql = "select * from t_user where userName=? and passWord=?";
14         List<User> userlist = this.executeDQL(User.class, sql, userName, passWord);
15         
16         return null!= userlist&&!userlist.isEmpty()?userlist.get(0):null;
17     }
18 
19     
20     
21     /**
22      * @param args
23      */
24     public static void main(String[] args) {
25         //测试executeDQL
26 //        User user = new UserDaoImpl().selectUser("ligang", "123456");
27 //        System.out.println(user);
28     
29         //测试executeInsert
30 //        String sql = "insert into t_user(username,password,realname,weight,height,birthday) values(?,?,?,?,?,?),(?,?,?,?,?,?)";
31 //        List<Integer> pkList =  new UserDaoImpl().executeInsert(Integer.class, sql, "zhangsan","123456","张三",75.55,176,Date.valueOf("1997-6-6"),"lisi","lisi","张三",55.55,176,Date.valueOf("2005-6-6"));
32 //        System.out.println("主键列表:"+pkList);
33 //        System.out.println("影响行数:"+pkList.size());
34         
35         //测试executeDML
36         String sql = "update t_user set username=?,password=?,realname=?,weight=?,height=?,birthday=? where userid=?";
37         Integer count =  new UserDaoImpl().executeDML( sql, "ligang","123456","张三",75.55,176,Date.valueOf("1997-6-6"),1);
38         System.out.println("影响行数:"+count);
39     }
40 }
UserDaoImpl

==========这是华丽的分割线============

发现自己的BaseDao中的连接数据库的部分写的太固定;比如你需要修改密码时,需要改源代码,然后提交到运维测试,需要走一大圈流程;所以接下来我们把连接数据库的部分写到一个文本中,这样子需要修改时就不需要修改源代码了;

首先将如下代码进行一定修改,写到src下的db.properties中:

url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8";
driver="com.mysql.jdbc.Driver";
userName = "root";
passWord = "123456";
需修改部分

 在db.properties文件中时以键值对的形式存储的;以第一个等号为分界线,默认左右都为字符串,=左边为键,右边为值;为了便于阅读,如使用的是jdbc的,就用jdbc.xxx

jdbc.url = jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.userName = root
jdbc.passWord =123456
db.properties
package com.mmzs.bigdata.dao;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class BaseDao {
    //URL指向要访问的数据库名mydata
    private static String url;
    //驱动程序名
    private static String driver;
    //MySQL配置时的用户名
    private static String userName;
    //MySQL配置时的密码
    private static String passWord;
    /**
     * 连接数据库的驱动
     */
    static {
        try {
            Properties properties = new Properties();
            
            //此处/表示src根路径;创建指向磁盘文件中属性文件的输入流
            InputStream fis = BaseDao.class.getResourceAsStream("/db.properties");
            //将属性文件中的内容从磁盘读入到内存中
            properties.load(fis);
            //取连接数据库的参数值
            url = properties.getProperty("jdbc.url");
            driver = properties.getProperty("jdbc.driver");
            userName = properties.getProperty("jdbc.userName");
            passWord = properties.getProperty("jdbc.passWord");
            //将驱动类装载到JVM内存的方法区
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 返回数据库链接
     * @return
     */
    public Connection getConnection() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, userName, passWord);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return conn;
    }
    
    /**
     * 执行通用插入操作
     * @param pkClass
     * @param sql
     * @param params
     * @return 主键列表(主键列表的长度代表插入函数的影响函数)
     */
    public <T> List<T> executeInsert(Class<T> pkClass, String sql, Object... params) {
        //获取数据库连接
        Connection conn = getConnection();
        if (null == conn) return null;
        
        T t = null;
        ResultSet pkRes = null;
        PreparedStatement pstat = null;
        List<T> pkList = new ArrayList<T>();
        try {
            //预编译SQL语句
            pstat = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
            //为预编译好的SQL语句传递参数
            for (int i = 0; i < params.length; i++) {
                pstat.setObject(i+1, params[i]);
            }
            //执行增删改等操作返回影响的行数
            pstat.executeUpdate();
            //获取生成的主键结果集
            pkRes = pstat.getGeneratedKeys();
            //遍历主键结果集
            while (pkRes.next()) {
                //主键结果集中的每一条记录只有一列(这一列代表主键值),所以只能取下标1
                t = (T) pkRes.getObject(1);
                pkList.add(t);
            }
            return pkList;
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != pkRes) {
                    pkRes.close();
                }
                if (null != pstat) {
                    pstat.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        return null;
    }
    
    /**
     * 执行通用的增删改
     * @param sql
     * @param params
     * @return 影响行数
     */
    public Integer executeDML(String sql, Object... params) {
        //获取数据库连接
        Connection conn = getConnection();
        if (null == conn) return null;
        
        Integer count = null;
        PreparedStatement pstat = null;
        //为预编译好的SQL语句传递参数
        try {
            //预编译SQL语句
            pstat = conn.prepareStatement(sql);
            //为预编译好的SQL语句传递参数
            for (int i = 0; i < params.length; i++) {
                pstat.setObject(i+1, params[i]);
            }
            //执行增删改等操作
            count = pstat.executeUpdate();
            return count;
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != pstat) {
                    pstat.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }
    
    /**
     * 执行数据库查询操作
     * @param entityClass
     * @param sql
     * @param params
     * @return 结果集
     */
    public <T> List<T> executeDQL(Class<T> entityClass, String sql, Object... params) {
        //获取数据库连接
        Connection conn = getConnection();
        if (null == conn) {
            return null;
        }
        //
        ResultSet res = null;
        //对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的
        PreparedStatement pstat = null;//import java.sql.PreparedStatement;
        List<T> list = new ArrayList<>();
        try {
            //预编译SQL语句
            pstat = conn.prepareStatement(sql);
            //为预编译好的SQL语句传递参数
            for (int i = 0; i < params.length; i++) {
                pstat.setObject(i+1, params[i]);
            }
            //执行SQL语句并返回结果集
            res = pstat.executeQuery();
            //获取结果集元数据
            ResultSetMetaData rsmd = res.getMetaData();
            //获取结果集中列的数量(字段的数量)
            Integer columnNum = rsmd.getColumnCount();
            
            //简单类型包括数字类型、字符串类型和日期类型
            if (String.class.isAssignableFrom(entityClass) ||
                    Number.class.isAssignableFrom(entityClass) ||
                    Date.class.isAssignableFrom(entityClass)) {//简单类型
                T t = null;
                //遍历每一条记录
                while (res.next()) {
                    //类型转换必须类型兼容;低类型向高类型自动转换,反之强制转换;
                    t = (T)res.getObject(1);//返回单例,索引只能去1
                    list.add(t);
                }
            }else if(Map.class.isAssignableFrom(entityClass)) {//字典类型,Map是顶层接口
                T t = null;
                //获取的是类自身声明的所有方法
                Method putMethod = entityClass.getDeclaredMethod("put", Object.class, Object.class);
                while (res.next()) {
                    //调用反射调用Map实现累的无参数构造创建Map实例对象
                    t = entityClass.newInstance();
                    //循环每条记录中的各个字段
                    for (int i = 0; i < columnNum; i++) {
                        //获取列名(它对应于Map中的Key)
                        String fieldName = rsmd.getColumnLabel(i+1);
                        //获取列值(它对应于Map中的Value)
                        Object fieldValue = res.getObject(fieldName);
                        //调用put方法往Map中添加键值对
                        putMethod.invoke(t, fieldName, fieldValue);
                    }
                    list.add(t);
                }
            }else { //实体类型
                T t = null;
                while (res.next()) {
                    //使用反射调用实体类的无参数构造创建实体对象
                    t = entityClass.newInstance();
                    for (int i = 0; i < columnNum; i++) {
                        //获取结果集中的字段名(或别名)
                        String fieldName = rsmd.getColumnLabel(i+1);
                        //1.根据字段名获取字段值
                        Object fieldValue = res.getObject(fieldName);
                        //2.根据索引获取字段值
                        //Object fieldValue = res.getObject(i+1);
                        //getDeclaredField是可以获取一个类的所有字段. 
                        //通过反射根据字段名查找实体类(User类)中的属性
                        java.lang.reflect.Field field = entityClass.getDeclaredField(fieldName);
                        //打开访问权限
                        field.setAccessible(true);
                        field.set(t, fieldValue);
                    }
                    list.add(t);
                }
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != res) {
                        res.close();
                }
                if (null != pstat) {
                    pstat.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
}
BaseDao

==========这是华丽的分割线============

接下我们尝试将sql语句写到文本文件中来读取,优点同上;

首先,在工程中导入jar包:xstream-all-1.4.7.jar;
然后,在UserDaoImpl 中测试xstream包的一些用法;
package com.mmzs.bigdata.dao;

import java.sql.Date;
import java.util.List;

import com.mmzs.bigdata.po.User;

public class UserDaoImpl extends BaseDao implements UserDao {

    @Override
    public User selectUser(String userName, String passWord) {
        
        String sql = "select * from t_user where userName=? and passWord=?";
        List<User> userlist = this.executeDQL(User.class, sql, userName, passWord);
        
        return null!= userlist&&!userlist.isEmpty()?userlist.get(0):null;
    }

    
    
    /**
     * 测试xml的相关操作
     */
    public static void main(String[] args) {

        Map<String, Object> user = new HashMap<String, Object>();
        user.put("userId", 12);
        user.put("userName", "ligang");
        user.put("passWord", "liagan");
        
        
        System.out.println("======序列化======");
        XStream stream = new XStream();
        String xml = stream.toXML(user);
        System.out.println(xml);
        
        System.out.println("======反序列化======");
        Map<String, Object> newUser = (Map<String, Object>) stream.fromXML(xml);
        String userName = (String) newUser.get("userName"); 
        System.out.println(newUser+"==="+userName);
    }
}
UserDaoImpl

 最后,在src下面新建sql.xml;

<?xml version="1.0" encoding="UTF-8"?>
<map>
  <entry>
    <string>selectUser</string>
    <string>select * from t_user where userName=? and passWord=?</string>
  </entry>
</map>
sql.xml

在UserDaoImpl 中进行最终测试;

package com.mmzs.bigdata.dao;

import java.io.InputStream;
import java.sql.Date;

public class UserDaoImpl extends BaseDao implements UserDao {

    private Map<String, String> sqlMap;
    
    public UserDaoImpl() {
        XStream stream = new XStream();
        InputStream fis = UserDao.class.getResourceAsStream("/sql.xml");
        sqlMap = (Map<String, String>) stream.fromXML(fis);
    }
    
    @Override
    public User selectUser(String userName, String passWord) {
        
        String sql = sqlMap.get("selectUser");
        List<User> userlist = this.executeDQL(User.class, sql, userName, passWord);
        
        return null!= userlist&&!userlist.isEmpty()?userlist.get(0):null;
    }
    

    
    public static void main(String[] args) {
        
         User user = new UserDaoImpl().selectUser("ligang", "123456");
         System.out.println(user);
        
    }
}
UserDaoImpl

==========这是华丽的分割线============

 现在准备工作就绪,我们开始写登录页面进行登陆验证:

因为Dao层已经写完了,所以直接开始写Service实现层:

 1 package com.mmzs.bigdata.service;
 2 
 3 import com.mmzs.bigdata.dao.UserDao;
 4 import com.mmzs.bigdata.dao.UserDaoImpl;
 5 import com.mmzs.bigdata.po.User;
 6 
 7 public class UserServiceImpl implements UserService {
 8 
 9     private UserDao userDao;
10     
11     public UserServiceImpl() {
12         userDao = new UserDaoImpl();
13     }
14     
15     
16     @Override
17     public User getUser(String userName, String passWord) {
18         return userDao.selectUser(userName, passWord);
19     }
20 
21 }
UserServiceImpl

然后完善UserAction类: 

 1 package com.mmzs.bigdata.action;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import com.mmzs.bigdata.po.User;
10 import com.mmzs.bigdata.service.UserService;
11 import com.mmzs.bigdata.service.UserServiceImpl;
12 
13 /**
14  * 用户模块控制器
15  * @author Administrator
16  *
17  */
18 public class UserAction extends BaseAction {
19     
20     private UserService userService;
21     
22     public UserAction() {
23         userService = new UserServiceImpl();
24     }
25     /**
26      * 用户登录
27      * @param request
28      * @param response
29      * @throws IOException 
30      * @throws ServletException 
31      */
32     public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
33         String userName = request.getParameter("userName");
34         String passWord = request.getParameter("passWord");
35         User user = userService.getUser(userName, passWord);
36         if (null != user) {//登陆成功
37             request.getSession().setAttribute("loginUser", user);
38             request.getRequestDispatcher("/main.jsp").forward(request, response);
39             System.out.println("登陆成功!");
40             return;//如果你是一个比较有良知的人,加一个return;因为加了执行到此处就结束,否则会往下执行自动结束;理论上加与不加效果相同;
41         } else {//登录失败
42             request.setAttribute("loginError", "用户名或密码输入错误");
43             request.getRequestDispatcher("/login.jsp").forward(request, response);
44         }
45     }
46 }
UserAction

 写出UserAction类成功和失败返回的界面:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">

  </head>
  
  <body>
    
  </body>
</html>
登陆成功!
main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
    <script type="text/javascript">
        //用于验证登陆参数
        function validate(Form)    {
            var userName = Form.userName.value;
            var passWord = Form.passWord.value;
            
            if(""==userName || ""==passWord) {
                alert("请完整的输入用户名和密码");
                return false;//取消表但提交            
            }
        }
    </script>
  </head>
  
  <body>
    <span style="font-size: 22px;font-weight: bolder;color: red">用户登陆</span>
    <hr color="green" size="2" width="100%" />
    <form id="loginForm" action="/BigData6-1/userAction" method="post">
        <input type="hidden" name="method" value="login">
        <input name="userName" ><br><br>
        <input name="passWord" type="password"  ><br><br>
        <!-- 只有带了name属性的才会被提交到服务器 -->
        <input type="submit" value="登录" onclick="return validate(this.form)">
    </form>
    <span style="font-size: 14px;font-weight: bolder;color: red">${loginError }</span>
  </body>
</html>
login.jsp

写到此处,整个程序整体已经比较完整了;

==========这是华丽的分割线============

接下来,我们增加点用户,然后打算做一个用户列表的分页查询:

 1、首先就需要在dao层写一个查询所有用户的方法

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <map>
 3   <entry>
 4     <string>selectUser</string>
 5     <string>select * from t_user where userName=? and passWord=?</string>
 6   </entry>
 7   <entry>
 8     <string>selectUserList</string>
 9     <string>select * from t_user limit ?,?</string>
10   </entry>
11     <entry>
12     <string>selectUserCount</string>
13     <string>select count(1) from t_user</string>
14   </entry>
15 </map>
UserDaoImpl中需要的sql语句文件:sql.xml
        /**
     * 根据通用查询查询用户
     * @param params
     * @return
     */
    public List<User> selectUserList(Map<String, Object> params);    
UserDao
        @Override
    public List<User> selectUserList(Map<String, Object> params) {
        Integer start = (Integer) params.get("start");
        Integer count = (Integer) params.get("count");
        
        String sql = sqlMap.get("selectUserList");
        List<User> userList = executeDQL(User.class, sql, start, count);
        
        return userList;
    }    
UserDaoImpl

 2、写出service层

        /**
     * @param curPage 跳转到的目标也
     * @param count 每页显示的记录数量
     * @return 分页字典对象
     */
    public Map<String, Object> getUserList(Integer curPage, Integer count);
UserService
package com.mmzs.bigdata.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mmzs.bigdata.dao.UserDao;
import com.mmzs.bigdata.dao.UserDaoImpl;
import com.mmzs.bigdata.po.User;

public class UserServiceImpl implements UserService {

    private UserDao userDao;
    
    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }
    
    
    @Override
    public User getUser(String userName, String passWord) {
        return userDao.selectUser(userName, passWord);
    }


    @Override
    public Map<String, Object> getUserList(Integer curPage, Integer count) {
        //计算分页的起始索引
        Integer start = (curPage-1)*count;
        
        //包装分页字典
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("start", start);
        params.put("count", count);
        
        //通过分页参数查询分页数据
        List<User> userList = userDao.selectUserList(params);
        //查询表的总记录数量
        Integer totalCount = userDao.selectUserCount();
        //计算总页数
        Integer totalPage = totalCount/count;
        if (totalCount%count != 0) {//如果有余数,则总页数加1
            totalPage++;
        }
        
        //包装分页数据字典
        Map<String, Object> resMap = new HashMap<String, Object>();
        resMap.put("userList", userList);
        resMap.put("curPage", curPage);
        resMap.put("totalPage", totalPage);
        
        
        
        return resMap;
    }

}
UserServiceImpl
 1 package com.mmzs.bigdata.action;
 2 
 3 import java.io.IOException;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import com.mmzs.bigdata.po.User;
12 import com.mmzs.bigdata.service.UserService;
13 import com.mmzs.bigdata.service.UserServiceImpl;
14 
15 /**
16  * 用户模块控制器
17  * @author Administrator
18  *
19  */
20 public class UserAction extends BaseAction {
21     
22     private UserService userService;
23     
24     public UserAction() {
25         userService = new UserServiceImpl();
26     }
27     /**
28      * 用户登录
29      * @param request
30      * @param response
31      * @throws IOException 
32      * @throws ServletException 
33      */
34     public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
35         String userName = request.getParameter("userName");
36         String passWord = request.getParameter("passWord");
37         
38         User user = userService.getUser(userName, passWord);
39         if (null != user) {//登陆成功
40             request.getSession().setAttribute("loginUser", user);
41             Map<String, Object> resMap = userService.getUserList(1, COUNT);
42 
43             request.setAttribute("curPage", resMap.get("curPage"));
44             request.setAttribute("totalPage", resMap.get("totalPage"));
45             request.setAttribute("userList", resMap.get("userList"));
46             System.out.println(resMap);
47             request.getRequestDispatcher("/main.jsp").forward(request, response);
48             return;//如果你是一个比较有良知的人,加一个return;因为加了执行到此处就结束,否则会往下执行自动结束;理论上加与不加效果相同;
49         } else {//登录失败
50             request.setAttribute("loginError", "用户名或密码输入错误");
51             request.getRequestDispatcher("/login.jsp").forward(request, response);
52         }
53     }
54 }
UserAction

每页显示的记录数量

        /**
     * 每页显示的记录数量
     */
    protected static final Integer COUNT = 5;        
BaseAction

在BaseAction中用一个常量固定化,分页所需要的参数:

    /**
     * 总数量
     * @return
     */
    public Integer selectUserCount();
UserDao
    @Override
    public Integer selectUserCount() {
        String sql = sqlMap.get("selectUserCount");
        List<Long> counts = executeDQL(Long.class, sql);
        return null!= counts&&!counts.isEmpty()?counts.get(0).intValue():null;
    }
UserDaoImpl

 写界面,并且分页所需参数名字保持一致:

 1 <%@ page language="java" pageEncoding="UTF-8"%>
 2 <script type="text/javascript">
 3     var curPage=${curPage}
 4     var totalPage=${totalPage}
 5 
 6     //首页
 7     function firstPage(){
 8         if(curPage<=1){
 9             alert("当前页已经是第一页!");
10             return;
11         }
12         sepPage(1);//执行翻页(翻到第一页)
13     }
14     
15     //上一页
16     function prePage(){
17         if(curPage<=1){
18             alert("当前页已经是第一页!");
19             return;
20         }
21         sepPage(curPage-1);//执行翻页
22     }
23     
24     //下一页
25     function nextPage(){
26         if(curPage>=totalPage){
27             alert("当前页已经是末页!");
28             return;
29         }
30         sepPage(curPage+1);//执行翻页
31     }
32     
33     //末页
34     function lastPage(){
35         if(curPage>=totalPage){
36             alert("当前页已经是末页!");
37             return;
38         }
39         sepPage(totalPage);//执行翻页
40     }
41     
42     //跳转到
43     function gotoPage(){
44         var toPage=document.getElementById("toPage").value;
45         var rex=/^\d+$/
46         if(!rex.test(toPage)||parseInt(toPage)<1||parseInt(toPage)>totalPage){
47             alert("输入的页号不合理!");
48             return;
49         }
50         if(parseInt(curPage)==parseInt(toPage)){
51             alert("当前页已经是你输入的页号");
52             return;
53         }
54         sepPage(toPage);
55     }
56 </script>
57 <div style="text-align: center;">
58     <pre style="display: inline;font-size:16px;">当前是第:${curPage}/${totalPage}页 </pre>
59     <input type="button" value="首页" onclick="firstPage()"/>
60     <input type="button" value="上一页" onclick="prePage()"/>
61     <input type="button" value="下一页" onclick="nextPage()"/>
62     <input type="button" value="末页" onclick="lastPage()"/>
63     <input type="button" value="跳转到" onclick="gotoPage()"/>
64     <input id="toPage" name="toPage" style="width:50px;"/>65 </div>
paging.jsp
导入分页jsp中需要的js:js.zip
在返回的主页面回显:
 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"  %>
 3 <%
 4 String path = request.getContextPath();
 5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 6 %>
 7 
 8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 9 <html>
10   <head>
11     <base href="<%=basePath%>">
12     
13     <title>My JSP 'login.jsp' starting page</title>
14     
15     <meta http-equiv="pragma" content="no-cache">
16     <meta http-equiv="cache-control" content="no-cache">
17     <meta http-equiv="expires" content="0">    
18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
19     <meta http-equiv="description" content="This is my page">
20     <style type="text/css">
21         table,td,th{
22             border: 1px solid black;
23             height: 20px;
24         }
25     </style>
26 
27   </head>
28   
29   <body>
30     <span style="font-size: 22px;font-weight: bolder;color: red">用户信息表</span>
31     <hr color="green" size="2" width="100%" />
32     <div id="dataDiv">
33         <table weight="600" height="400" cellpadding="0" cellspacing="0">
34             <thead>
35                 <tr>
36                     <th>
37                         <input type="checkbox" id="allSel">全选
38                     </th>
39                     <th>用户名</th>
40                     <th>密码</th>
41                     <th>姓名</th>
42                     <th>体重</th>
43                     <th>身高</th>
44                     <th>生日</th>
45                     <th>操作</th>
46                 </tr>
47             </thead>
48             <tbody>
49             <c:forEach items="${userList }" var="user" varStatus="stat">
50                 <tr>
51                     <td><input type="checkbox" name="userIds" value="${user.userId }"></td>
52                     <td>${user.userName }</td>
53                     <td>${user.passWord }</td>
54                     <td>${user.realName }</td>
55                     <td>${user.weight }</td>
56                     <td>${user.height }</td>
57                     <td>${user.birthday }</td>
58                     <td>
59                         <input type="button" value="删除">
60                         <input type="button" value="修改">
61                     </td>
62                 </tr>
63             </c:forEach>
64             </tbody>
65         </table>
66     </div>
67   </body>
68 </html>
main.jsp

 进行到此时,测试代码,成功登陆就已经能够得到用户列表了。

 ==========这是华丽的分割线============
 完善main.jsp页面:添加分页功能,实现最简单的一种分页方式;
    <script type="text/javascript">
        //分页函数
        function sepPage(toPage) {
            window.location.href="/BigData6-1/userAction?method=list&curPage="+toPage;
            
        }
    </script>
添加script调用分页UserAction中的list方法
                       <tfoot>
                <tr>
                    <td colspan="8">
                        <%@ include file="paging.jsp" %>
                    </td>
                </tr>
            </tfoot>
在main.jsp中引入paging.jsp
    /**
     * 列表分页
     * @param request
     * @param response
     * @throws IOException 
     * @throws ServletException 
     */
    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String curPage = request.getParameter("curPage");
        Map<String, Object> resMap = userService.getUserList(Integer.parseInt(curPage), COUNT);
        
        request.setAttribute("curPage", resMap.get("curPage"));
        request.setAttribute("totalPage", resMap.get("totalPage"));
        request.setAttribute("userList", resMap.get("userList"));
        
        request.getRequestDispatcher("/main.jsp").forward(request, response);
    }
UserAction中的list方法

 进行到此时,测试代码,成功登陆就已经能够得到用户列表并操作分页功能了。

 ==========这是华丽的分割线============
接下来我们将数据传递方式修改成ajax的方式:
<script type="text/javascript">
        //分页函数
        function sepPage(toPage) {
            //window.location.href="/BigData6-1/userAction?method=list&curPage="+toPage;
            //var div = $("div#dataDiv").get(0);
            //ajax回调函数
            function callBack(data){
                $("div#dataDiv").html(data);
            }
            /*
            * A、如果需要get方式提交则可以调$.get(…)
                B、get与post一共有四个参数:
                第一个参数:提交的服务端地址
                第二个参数:提交到服务端的参数
                第三个参数:服务端成功响应回来之后的回调函数,回调函数的参数表示服务端响应回来的数据
                第四个参数:服务端响应回来的数据格式(html、json、xml)
            */
            $.post("/BigData6-1/userAction",
                    "method=list&curPage="+toPage,
                    callBack,
                    "html")
        }
    </script>
重写分页函数sepPage
        /**
     * 列表分页
     * @param request
     * @param response
     * @throws IOException 
     * @throws ServletException 
     */
    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String curPage = request.getParameter("curPage");
        Map<String, Object> resMap = userService.getUserList(Integer.parseInt(curPage), COUNT);
        //大公司操作
//        StringWriter writer = new StringWriter();
//        ObjectMapper mapper = new ObjectMapper();
//        mapper.writeValue(writer, resMap);
//        String jsonString = writer.toString();
//        response.getWriter().write(jsonString);
        
        //小公司操作
        request.setAttribute("curPage", resMap.get("curPage"));
        request.setAttribute("totalPage", resMap.get("totalPage"));
        request.setAttribute("userList", resMap.get("userList"));
        //request.getRequestDispatcher("/main.jsp").forward(request, response);
        request.getRequestDispatcher("/table.jsp").forward(request, response);
    }    
重写UserAction中的list方法
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"  %>
        <table weight="600" height="400" cellpadding="0" cellspacing="0">
            <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="allSel">&nbsp;全选
                    </th>
                    <th>用&nbsp;户&nbsp;名</th>
                    <th>密&nbsp;&nbsp;码</th>
                    <th>姓&nbsp;&nbsp;名</th>
                    <th>体&nbsp;&nbsp;重</th>
                    <th>身&nbsp;&nbsp;高</th>
                    <th>生&nbsp;&nbsp;日</th>
                    <th>操&nbsp;&nbsp;作</th>
                </tr>
            </thead>
            <tbody>
            <c:forEach items="${userList }" var="user" varStatus="stat">
                <tr>
                    <td><input type="checkbox" name="userIds" value="${user.userId }"></td>
                    <td>${user.userName }</td>
                    <td>${user.passWord }</td>
                    <td>${user.realName }</td>
                    <td>${user.weight }</td>
                    <td>${user.height }</td>
                    <td>${user.birthday }</td>
                    <td>
                        <input type="button" value="删除">
                        <input type="button" value="修改">
                    </td>
                </tr>
            </c:forEach>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="8">
                        <%@ include file="paging.jsp" %>
                    </td>
                </tr>
            </tfoot>
        </table>
添加table.jsp页面;其实就是main.jsp页面中的table部分

 进行到此时,测试代码,成功登陆就,同样能够得到用户列表并操作分页功能,只是此时我们使用的传值的方式不同了。

  ==========这是华丽的分割线============
 这时又来一个需求,用户登陆后不想全部查询出来用户,只想查询部分用户;比如查询名字带"李"的人;(%三%:表示模糊查询)
首先需要在sql.xml中添加sql语句:
  <entry>
    <string>selectUserListByCondition</string>
    <string>select * from t_user where realName like ? limit ?,?</string>
  </entry>
  <entry>
    <string>selectUserCountByCondition</string>
    <string>select count(1) from t_user where realName like ?</string>
  </entry>
sql.xml

 在main方法中添加:

<form id="queryForm">
        <input type="hidden" name="method" value="list" />
        <input type="hidden" name="curPage" value="1" />
        姓名:<input name="realName" />
        <input type="button" value="查询" onclick="sepPage(1)" />
        
</form>
    <div id="dataDiv">
main.jsp
并完善script中定义的function函数seppage:
<script type="text/javascript">
        //分页函数
        function sepPage(toPage) {
            var JForm = $("form#queryForm");
            //获取name=curPage的输入框中的值
            $("input[name=curPage]:hidden",JForm).val(toPage);
            //序列表表格内容为字符串。
            var queryString = JForm.serialize();
            
            //ajax回调函数
            function callBack(data){
                $("div#dataDiv").html(data);
            }
            /*
            * A、如果需要get方式提交则可以调$.get(…)
                B、get与post一共有四个参数:
                第一个参数:提交的服务端地址
                第二个参数:提交到服务端的参数
                第三个参数:服务端成功响应回来之后的回调函数,回调函数的参数表示服务端响应回来的数据
                第四个参数:服务端响应回来的数据格式(html、json、xml)
            */
            $.post("/BigData6-1/userAction",
                    queryString,
                    callBack,
                    "html")
        }
    </script>
sepPage函数

 此时sepPage函数调用的是Action的list函数,由于之前都是实用的service层的getUserList函数来进行具体操作,但是之前都是只传递了两个参数(但前页curPage和每页显示的记录数COUNT);要修改起来比较麻烦,所以我们此时选择new一个Map来传参;则:

    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String curPage = request.getParameter("curPage");//curPage得到的是String类型需转化为integer类型
        String realName = request.getParameter("realName");
        realName = new String(realName.getBytes("ISO-8859-1"), "UTF-8");//需要转码中文才能搞定
        
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("curPage", Integer.parseInt(curPage));
        args.put("count", COUNT);
        if (null != realName && !realName.trim().isEmpty()) {
            args.put("realName", realName);
        }
        
        
        Map<String, Object> resMap = userService.getUserList(args);
Action中函数list的修改
public Map<String, Object> getUserList(Map<String, Object> params);
UserService中getUserList参数修改
    @Override
    public Map<String, Object> getUserList(Map<String, Object> args) {
        //取出分页查询参数
        Integer curPage =  (Integer)args.get("curPage");
        Integer count = (Integer) args.get("count");
        String realName =  (String) args.get("realName");

        //计算分页的起始索引
        Integer start = (curPage-1)*count;
        //包装分页字典
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("start", start);
        params.put("count", count);
                
        
        if (null != realName) {//分页查询显示列表
            params.put("realName", "%"+realName+"%");
        }            
        
        //查询表的总记录数量
        Integer totalCount = userDao.selectUserCount(params);
        //计算总页数
        Integer totalPage = totalCount/count;
        if (totalCount%count != 0) {//如果有余数,则总页数加1
            totalPage++;
        }
        
        //通过分页参数查询分页数据
        List<User> userList = userDao.selectUserList(params);
UserServiceImple的getUserList函数实现做的修改
    @Override
    public Integer selectUserCount(Map<String, Object> params) {
        Object realName = params.get("realName");
        List<Number> counts = null;
        if (null == realName) {//登陆之后查询表的总数量
            String sql = sqlMap.get("selectUserCount");
            counts = executeDQL(Number.class, sql);//用Number可以避免一切返回类型不兼容问题
        }else { //条件查询总数量
            String sql = sqlMap.get("selectUserCountByCondition");
            counts = executeDQL(Number.class, sql, realName);
        }
        return null!= counts&&!counts.isEmpty()?counts.get(0).intValue():null;
    }
UserServiceImpl中调用的dao层的selectUserCount的优化
@Override
    public List<User> selectUserList(Map<String, Object> params) {
        Integer start = (Integer) params.get("start");
        Integer count = (Integer) params.get("count");
        Object realName = params.get("realName");
        
        List<User> userList = null;
        
        if (null == realName) {//登陆之后显示主页列表
            String sql = sqlMap.get("selectUserList");
            userList = executeDQL(User.class, sql, start, count);
        }else { //条件查询加分页显示列表
            String sql = sqlMap.get("selectUserListByCondition");
            userList = executeDQL(User.class, sql, realName, start, count);
        }
        return userList;
    }
UserServiceImpl中调用的dao层的selectUserList的优化

  进行到此时,测试代码,成功登陆就,同样能够得到用户列表并操作分页功能。

  ==========这是华丽的分割线============

 此时有个用户注册的页面,注册时需要上传头像,保存到数据库,能正确表现出来。
所以需要写个register.jsp页面;数据传递方式采用json;代码如下
在这里我犯了一个严重的错误:register.jsp页面中的register函数中的传值部分的dataType属性名写错了,写成dateType;这两个单词很接近,查了好久都没找到,所以单词还是很关键啊。
    <script type="text/javascript">
        //用户注册函数
        function register(Form) {
            var dict = {
                url:"/BigData6-1/userAction?method=register",
                type:"post",
                //dataType:"xml",
                dataType:"json",
                beforeSubmit:function(dataDictList, JForm, options){
                    //此函数用于在提交表单之前进行验证,如果此函数返回false
                    //则取消表单的提交
                },
                success:function(jsonDict) {
                    //此函数是服务端成功响应回来之后需要回调的函数
                    $("input:button", Form).val("继续注册");
                    //修改图片的路径
                    $("img#userPhoto").attr("src",jsonDict.photoPath);
                    
                    
                    /*
                    //从XML文档中提取图片路径
                    var imgPath =$("body",xmlDoc).html();
                    alert(imgPath);
                    //修改图片的路径
                    $("img#userPhoto").attr("src",imgPath);
                    */
                }
                
            }

            
            //使用ajax提交带有文件域的表单
            $(Form).ajaxSubmit(dict);
            
            
            
            
        }
    
    
    </script>
View Code
  1 package com.mmzs.bigdata.action;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 import java.io.PrintWriter;
  6 import java.io.StringWriter;
  7 import java.sql.Date;
  8 import java.util.HashMap;
  9 import java.util.List;
 10 import java.util.Map;
 11 
 12 import javax.jms.ObjectMessage;
 13 import javax.servlet.ServletException;
 14 import javax.servlet.http.HttpServletRequest;
 15 import javax.servlet.http.HttpServletResponse;
 16 
 17 import org.apache.commons.fileupload.FileItem;
 18 import org.codehaus.jackson.map.ObjectMapper;
 19 
 20 import com.mmzs.bigdata.po.User;
 21 import com.mmzs.bigdata.service.UserService;
 22 import com.mmzs.bigdata.service.UserServiceImpl;
 23 import com.thoughtworks.xstream.mapper.Mapper;
 24 
 25 /**
 26  * 用户模块控制器
 27  * @author Administrator
 28  *
 29  */
 30 /**
 31  * @author Administrator
 32  *
 33  */
 34 public class UserAction extends BaseAction {
 35     
 36     private UserService userService;
 37     
 38     public UserAction() {
 39         userService = new UserServiceImpl();
 40     }
 41     /**
 42      * 用户登录
 43      * @param request
 44      * @param response
 45      * @throws IOException 
 46      * @throws ServletException 
 47      */
 48     public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 49         String userName = request.getParameter("userName");
 50         String passWord = request.getParameter("passWord");
 51         
 52         User user = userService.getUser(userName, passWord);
 53         if (null != user) {//登陆成功
 54             request.getSession().setAttribute("loginUser", user);
 55             Map<String, Object> args = new HashMap<String, Object>();
 56             args.put("curPage", 1);
 57             args.put("count", COUNT);
 58             Map<String, Object> resMap = userService.getUserList(args);
 59 
 60             request.setAttribute("curPage", resMap.get("curPage"));
 61             request.setAttribute("totalPage", resMap.get("totalPage"));
 62             request.setAttribute("userList", resMap.get("userList"));
 63             request.getRequestDispatcher("/main.jsp").forward(request, response);
 64             return;//如果你是一个比较有良知的人,加一个return;因为加了执行到此处就结束,否则会往下执行自动结束;理论上加与不加效果相同;
 65         } else {//登录失败
 66             request.setAttribute("loginError", "用户名或密码输入错误");
 67             request.getRequestDispatcher("/login.jsp").forward(request, response);
 68         }
 69     }
 70     
 71     /**
 72      * 列表分页
 73      * @param request
 74      * @param response
 75      * @throws IOException 
 76      * @throws ServletException 
 77      */
 78     public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 79         String curPage = request.getParameter("curPage");//curPage得到的是String类型需转化为integer类型
 80         String realName = request.getParameter("realName");
 81         realName = new String(realName.getBytes("ISO-8859-1"), "UTF-8");//需要转码中文才能搞定
 82         
 83         Map<String, Object> args = new HashMap<String, Object>();
 84         args.put("curPage", Integer.parseInt(curPage));
 85         args.put("count", COUNT);
 86         if (null != realName && !realName.trim().isEmpty()) {
 87             args.put("realName", realName);
 88         }
 89         
 90         
 91         Map<String, Object> resMap = userService.getUserList(args);
 92         //大公司操作
 93 //        StringWriter writer = new StringWriter();
 94 //        ObjectMapper mapper = new ObjectMapper();
 95 //        mapper.writeValue(writer, resMap);
 96 //        String jsonString = writer.toString();
 97 //        response.getWriter().write(jsonString);
 98         
 99         //小公司操作
100         request.setAttribute("curPage", resMap.get("curPage"));
101         request.setAttribute("totalPage", resMap.get("totalPage"));
102         request.setAttribute("userList", resMap.get("userList"));
103         //request.getRequestDispatcher("/main.jsp").forward(request, response);
104         request.getRequestDispatcher("/table.jsp").forward(request, response);
105     }
106     
107     /**
108      * 用于处理用户注册
109      * @param request
110      * @param response
111      * @throws ServletException
112      * @throws IOException
113      */
114     public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
115         //解析带有文件域的表单提交请求
116         Map<String, List<Object>> paramMap = super.parseUpload(request);
117         
118         String userName = (String) paramMap.get("userName").get(0);
119         String passWord = (String) paramMap.get("passWord").get(0);
120         String realName = (String) paramMap.get("realName").get(0);
121         String weight = (String) paramMap.get("weight").get(0);
122         String height = (String) paramMap.get("height").get(0);
123         String birthday = (String) paramMap.get("birthday").get(0);
124         
125         FileItem photo = (FileItem) paramMap.get("photo").get(0);
126         //获取文件名
127         String fileName = photo.getName();
128         //图片在工程中的相对路径
129         String photoPath = "/BigData6-1/upload/"+fileName;
130         
131         System.out.println(userName+":"+realName+":"+birthday);
132         //利用注册的用户信息创建对象
133         User user = new User(userName, passWord, realName, Double.parseDouble(weight), Integer.parseInt(height), 
134                 Date.valueOf(birthday), photoPath);
135         //添加用户信息到数据库
136         Integer pk = userService.addUser(user);
137         System.out.println("主键:"+pk);
138         
139         
140         //将返回Ajax的信息包装成Json字典对象
141         Map <String, Object> jsonMap = new HashMap<String, Object>(); 
142         if (null != pk) {
143             jsonMap.put("addTip", "success");
144         }else {
145             jsonMap.put("addTip", "error");
146         }
147         
148         jsonMap.put("photoPath", photoPath);
149         
150         StringWriter writer = new StringWriter();
151         mapper.writeValue(writer,jsonMap);
152         String json = writer.toString();
153         
154         
155         
156         //获取文件需要保存的服务端路径
157         String filePath = this.getServletContext().getRealPath("/upload");
158         //根据文件服务端的绝对路径创建对象
159         File fileFullName = new File(filePath+File.separator+fileName);
160         PrintWriter pw = null;
161         try {
162             //存储文件到服务端指定的路径下
163             photo.write(fileFullName);
164             System.out.println(photoPath);
165             //response.setContentType("text/html;charset=UTF-8");//json格式需要这行代码;xml格式不需要这行代码
166             pw = response.getWriter();
167             pw.write(json);
168             System.out.println(pw);
169             pw.flush();
170             
171         } catch (Exception e) {
172             e.printStackTrace();
173         }finally{
174             if (null != pw) {
175                 pw.close();
176             }
177         }
178     }
179     
180 }
UserAction

 

 
 
 
 
 

 

如果,您希望更容易地发现我的博客,不妨收藏关注一下
原创公众号:Java学习之道
个人博客 : www.mmzsblog.cn


喜欢就推荐一下,因为你的参与是我在写作道路上的最强动力。
本文版权归作者淼淼之森和博客园共有,欢迎转载。
但须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2017-11-22 09:00  淼淼之森  阅读(944)  评论(0编辑  收藏  举报
  👉转载请注明出处和署名