在之前已经写过了jdbc的工具类,不过最近学习了新的方法,所以在这里重新写一遍,为后面的javaEE做铺垫;
首先我们要了解javaEE项目中,文件构成,新建一个javaEE项目,在项目中,有一个web文件夹,在web文件夹下有WEB-INF文件夹,我们的web.xml文件放在这个文件夹下,同时我们要新建两个文件夹,一个是classes文件夹,一个lib文件夹;
classes文件夹:我们做出来的程序,都是先编译成class文件,然后再jvm中运行class文件,所以运行时,并不需要java‘文件,因此要把编译好的class文件放在classes文件夹下,然后直接将web文件夹放在tomcat的webapps文件夹下就可以运行了。
这里写一下怎样将class文件放入classes文件夹:
我们先建四个包:
然后以建一个student表:
我们一这个表为基础,来模拟一次业务;
首先在entity中创建student表的实例化对象类Student:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.zs.entity; /** * 创建实例化是对象类Student * 生成get和set方法, * 空参及带参构造方法 * tostring方法*/ public class Student { // 1定义成员变量 private int id; private String sname; private int age; public Student() { super(); } public Student(int id, String sname, int age) { this.id = id; this.sname = sname; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", sname='" + sname + '\'' + ", age=" + age + '}'; } }
然后我们在util包创建jdbc的工具类:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.zs.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; /** * 1.导jar包,需要用到druid-1.0.9.jar, * mysql-connector-java-5.1.45-bin.jar, * servlet-api.jar * 需要用到阿里的连接池,所以需要配置文件,配置文件放在src文件夹下,配置文件的内容之前有介绍 */ public class DBUtils { private static DataSource ds; // 1.创建静态代码块读druid.properites配置文件,创建链接池 static { Properties p = new Properties(); InputStream in = DBUtils.class.getClassLoader().getResourceAsStream("druid.properties"); try { p.load(in); ds = DruidDataSourceFactory.createDataSource(p); } catch (Exception e) { e.printStackTrace(); } } // 2.创建获得连接对象的静态方法 public static Connection getConnection() throws SQLException { return ds.getConnection(); } // 3.创建增删改的方法,并返回布尔类型,使用可变参数来传递占位符的值 public static boolean executeUpdate(String sql,Object... args){ Connection conn = null; PreparedStatement ps = null; try { conn= getConnection(); ps = conn.prepareStatement(sql); // 通过for循环来给占位符赋值 for (int i = 0; i < args.length; i++) { ps.setObject(i+1,args[i]); } // 执行sql语句 int i = ps.executeUpdate(); return i>0; } catch (SQLException e) { e.printStackTrace(); }finally { close(conn,ps); } return false; } // 创建查询的方法,并返回list集合 public static List<Map<String, Object>> executeQuery(String sql, Object... args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn=getConnection(); ps = conn.prepareStatement(sql); // 遍历可变数组传递占位符值 for (int i = 0; i < args.length; i++) { ps.setObject(i+1,args[i]); } rs = ps.executeQuery(); List<Map<String,Object>> list=new ArrayList<>(); while (rs.next()) { Map<String, Object> map = new LinkedHashMap<>(); /**这里可能会有问题,为什么是String,Object类型,因为我们通过rs.next只能获得一行结果,这一行结果,我们如果直接存入集合中的的化就是一个一个的值 * 我们无法识别哪儿个值是那儿一列的,所以用想到用map集合来装结果,key为列名,所以用String,因为一行中有多种数据类型,所以用obj来保存,用linkedHashMap * 是因为map集合出来的结果是无序的,所以用linkedHashMap是有序的*/ // rs.getMetaData().getColumnCount();方法获得当前结果集的列数 for (int i = 0; i <rs.getMetaData().getColumnCount(); i++) { // 通过列的索引获得列名,i+1是因为没有第0列,从第一列开始 String key = rs.getMetaData().getColumnLabel(i + 1); // 通过键名来获得值 Object value = rs.getObject(key); map.put(key, value); } list.add(map); } return list; } catch (SQLException e) { e.printStackTrace(); }finally { close(conn,ps,rs); } return null; } // 创建关闭流的方法 private static void close(Connection conn) { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } // 重载 private static void close(Connection conn, PreparedStatement ps) { if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); }finally { close(conn); } } } // 重载 private static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); }finally { close(conn,ps); } } } }
然后我们写dao层的类:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.zs.dao; import com.zs.entity.Student; import java.util.List; import java.util.Map; /**我们首先在dao层下面创建接口,因为我们需要一个多态的特征,所以在接口中写抽象方法,方便后期的修改和维护 * 为什么要用多态,为了程序解耦,接触程序的耦合性,在创建后期修改时,如果我们要修改某一个方法,那就看可能会导致其他的方法不能运行, * 程序之间的联系就是耦合性,就像藕断丝连,越是复杂的程序,之间的联系就越多,而多态就是为了解耦*/ public interface IStudentDAO { /** * 在这里我们传递的参数为Student 对象 * 为什么要用student对象? * 因为在实际开发中,我们的表中的数据可能有很多列,我们不能把所有的列都当参数来传递,那样太麻烦了,而且不方便后期的修改和维护和, * 比如说,我们突然要删除一列,那么我们就要找到所有于该方法有关的方法,删除参数列表中相应的参数,这样太麻烦了,传递对象,我们通过get方法来获得参数*/ boolean add(Student s); boolean upd(Student s); boolean del(int id); List<Map<String,Object>> getStudentById(int id); List<Map<String,Object>> getAllStudent(); }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.zs.dao.impl; /** * 在创建完接口后,我们在dao层的下面新建一个impl文件夹,用来存放接口的实现类*/ import com.zs.dao.IStudentDAO; import com.zs.entity.Student; import com.zs.util.DBUtils; import java.util.List; import java.util.Map; public class StudentImpl implements IStudentDAO { @Override public boolean add(Student s) { String sql="insert into student(sname,age) value (?,?)"; // 通过get方法来传递占位符的值 return DBUtils.executeUpdate(sql, s.getSname(), s.getAge()); } @Override public boolean upd(Student s) { String sql = "update student set sname=? ,age=? where id=?"; return DBUtils.executeUpdate(sql, s.getSname(), s.getAge(), s.getId()); } @Override public boolean del(int id) { String sql = "delete from student where id=?"; return DBUtils.executeUpdate(sql, id); } @Override public List<Map<String, Object>> getStudentById(int id) { String sql = "select * from student where id=?"; return DBUtils.executeQuery(sql, id); } @Override public List<Map<String, Object>> getAllStudent() { String sql = "select * from student"; return DBUtils.executeQuery(sql); } }
然后我们在servlet包中建测试类来测试工具类:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.zs.servlet; import com.zs.dao.IStudentDAO; import com.zs.dao.impl.StudentImpl; import com.zs.entity.Student; import com.zs.util.DBUtils; import org.junit.Test; import java.util.List; import java.util.Map; public class StudentServlet { IStudentDAO is=new StudentImpl(); @Test public void add(){ Student stu = new Student(1, "张三", 20); // 这里这个 1 可能会有疑问,可以看一下dao层,我们插入语句中并没有用导id;写1是为了使用带参构造 boolean b = is.add(stu); if (b) { System.out.println("插入成功"); } else { System.out.println("插入失败"); } } @Test public void upd(){ Student stu = new Student(1, "张三", 20); boolean b = is.upd(stu); if (b) { System.out.println("修改成功"); } else { System.out.println("修改失败"); } } @Test public void del(){ boolean b = is.del(1); if (b) { System.out.println("删除成功"); } else { System.out.println("删除失败"); } } @Test public void sel(){ List<Map<String, Object>> list = is.getStudentById(2); if (list.size() > 0) { System.out.println(list); } else { System.out.println("该学生不存在"); } } @Test public void selAll(){ List<Map<String, Object>> list = is.getAllStudent(); System.out.println(list); } }
上面完成后,我们下面写一个页面,完成简单的表单验证,点击提交后,数据提交到后台,然后后台调用dao层,数据对比:
首先创建一个login表:
然后我们在dao层中创建ilogin接口:
package com.zs.dao; public interface ILoginDAO { boolean login(String username, String password); }
然后在impl文件夹中创建实现类:
package com.zs.dao.impl; import com.zs.dao.ILoginDAO; import com.zs.util.DBUtils; import java.util.List; import java.util.Map; public class LoginImpl implements ILoginDAO { @Override public boolean login(String username, String password) { String sql = "select * from login where sname=? and pwd=?"; List<Map<String, Object>> list = DBUtils.executeQuery(sql, username, password); return list.size()>0; } }
然后我们写一个简单的html页面,html页面放在web文件夹下;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录界面</title> </head> <body> <form action="/zs/login" method="post"> <input type="text" name="username" placeholder="请输入用户名"><br> <input type="password" name="password" placeholder="请输入密码"><br> <input type="submit" value="登录"> </form> </body> </html>
下面写登陆的后台Servlet:
package com.zs.servlet; import com.zs.dao.ILoginDAO; import com.zs.dao.impl.LoginImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "LoginServlet") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 将请求的数据转为utf-8的格式,没有这句话的话,会出现登录中文用户名失败 request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); ILoginDAO lo=new LoginImpl(); boolean b = lo.login(username, password); if (b) { System.out.println("登录成功"); // 成功跳转页面方法与下面一样,这里没有写可以跳转的页面 } else { System.out.println("登陆失败"); // 失败返回登录页面 response.sendRedirect("Login.html"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
配置tomcat的方法再之前写过,然后直接启动tomcat就好了